﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Diagnostics;

namespace JudgeKernel
{
    internal class CompileProcessor
    {
        public string guid;
        /// <summary>
        /// 代码
        /// </summary>
        public string code;
        /// <summary>
        /// 安全路径
        /// </summary>
        public string safePath;
        /// <summary>
        /// 编译器路径（无通配）
        /// </summary>
        public string compilePath;
        /// <summary>
        /// 编译参数
        /// </summary>
        public string compileParam;
        /// <summary>
        /// 代码路径（无通配）
        /// </summary>
        public string codePath;
        /// <summary>
        /// 可执行文件路径（无通配）
        /// </summary>
        public string exePath;
        /// <summary>
        /// 编译错误过滤器
        /// </summary>
        public string compileErrorFilter;
        /// <summary>
        /// 编译错误信息
        /// </summary>
        public string compileErrorInfo { get; private set; }

        public string Compile()
        {
            codePath = codePath.Replace("{safepath}", safePath)
                               .Replace("{guid}", guid);
            exePath = exePath.Replace("{safepath}", safePath)
                               .Replace("{guid}", guid);

            File.WriteAllText(codePath, code, Encoding.Default);

            var param = compileParam.Replace("{safepath}", safePath)
                                    .Replace("{codepath}", codePath)
                                    .Replace("{exepath}", exePath);

            var p = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = compilePath,
                    Arguments = param,
                    WorkingDirectory = safePath,
                    WindowStyle = ProcessWindowStyle.Hidden,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardError = true
                }
            };
            p.Start();
            p.WaitForExit(10000);
            if (!p.HasExited) p.Kill();

            File.Delete(codePath);
            if (File.Exists(exePath))
                return exePath;

            compileErrorInfo = p.StandardError.ReadToEnd();
            if (!string.IsNullOrEmpty(compileErrorFilter))
            {
                compileErrorFilter = compileErrorFilter.Replace("\r\n", "\n")
                                                       .Replace("{codepath}", codePath)
                                                       .Replace("{safepath}", safePath)
                                                       .Replace("{guid}", guid);
                foreach (var filter in compileErrorFilter.Split('\n'))
                    if (!string.IsNullOrWhiteSpace(filter))
                        compileErrorInfo = compileErrorInfo.Replace(filter.Trim(), "");
            }
            return null;
        }
    }
}
